﻿using Basefr.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Reflection;

namespace Basefr.Runtime.Extensions
{
    public static class EnumExtensions
    {
        public static string Description(this Enum val)
        {
            var field = val.GetType().GetField(val.ToString());
            var attribute = field.GetCustomAttribute<DescriptionAttribute>(false);
            return attribute?.Description ?? val.ToString();
        }

        public static string Abbrev(this Enum val)
        {
            var field = val.GetType().GetField(val.ToString());
            var attribute = field.GetCustomAttribute<AbbrevAttribute>(false);
            return attribute?.Description ?? val.ToString();
        }

        //public static string Description<T>(this Enum val) where T : DescriptionAttribute
        //{
        //    var field = val.GetType().GetField(val.ToString());
        //    var attribute = field.GetCustomAttribute<T>();
        //    return attribute?.Description ?? val.ToString();
        //}


        public static List<int> FlagValues(this Enum val)
        {
            var values = Enum.GetValues(val.GetType()).OfType<Enum>().Where(p => (p.GetHashCode() & val.GetHashCode()) != 0).Select(Convert.ToInt32).ToList();

            return values;
        }

        public static string[] FlagDescriptions(this Enum val)
        {
            var values = Enum.GetValues(val.GetType()).OfType<Enum>().ToList().FindAll(p => (p.GetHashCode() & val.GetHashCode()) != 0);

            return values.Select(Description).ToArray();
        }

        public static T MaxFlag<T>(this Enum val)
        {
            return Enum.GetValues(typeof(T)).OfType<Enum>().Where(p => (p.GetHashCode() & val.GetHashCode()) != 0).OrderByDescending(p => p.GetHashCode()).OfType<T>().FirstOrDefault();
        }

        public static string MaxFlagDescription(this Enum val)
        {
            if (val.GetHashCode() == 0)
            {
                return val.Description();
            }

            return Enum.GetValues(val.GetType()).OfType<Enum>()
                .Where(p => (p.GetHashCode() & val.GetHashCode()) != 0)
                .OrderByDescending(p => p.GetHashCode())
                .FirstOrDefault()?
                .Description();
        }

        public static T GetAttribute<T>(this Enum val) where T : Attribute
        {
            var field = val.GetType().GetField(val.ToString());
            var attribute = field.GetCustomAttribute<T>();
            return attribute;
        }

    }
}
